﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Common.Constants;
using Common.Interface;
using Common.Helper;

namespace MainProcessor.Processors
{
    public class LatestParentMeasuresProcessor : BaseElementProcessor, ILatestParentMeasures
    {
        public decimal? TotalCapacity { get { return GetValue<decimal?>(ParentMeasure.TotalCapacity.ToDescription(), XmlConstants.Value, GetLatest); } }
        public decimal? AuM { get { return GetValue<decimal?>(ParentMeasure.AuM.ToDescription(), XmlConstants.Value, GetLatest); } }
        public DateTime? AsOfDate { get; private set; }
        public decimal? AssetsInStrategy { get { return GetValue<decimal?>(ParentMeasure.AssetsInStrategy.ToDescription(), XmlConstants.Value, GetLatest); } }
        public decimal? FundSizeOffshore { get { return GetValue<decimal?>(ParentMeasure.FundSizeOffshore.ToDescription(), XmlConstants.Value, GetLatest); } }
        public decimal? CapacityOffShore { get { return GetValue<decimal?>(ParentMeasure.CapacityOffShore.ToDescription(), XmlConstants.Value, GetLatest); } }
        public decimal? CapacityReserved { get { return GetValue<decimal?>(ParentMeasure.CapacityReserved.ToDescription(), XmlConstants.Value, GetLatest); } }
        public decimal? FundSizeOnshore { get { return GetValue<decimal?>(ParentMeasure.FundSizeOnShore.ToDescription(), XmlConstants.Value, GetLatest); } }
        public decimal? MacSize { get { return GetValue<decimal?>(ParentMeasure.MacSize.ToDescription(), XmlConstants.Value, GetLatest); } }
        public short? TotalEmployees { get { return GetValue<short?>(ParentMeasure.TotalEmployees.ToDescription(), XmlConstants.Value, GetLatest); } }

        private static XElement GetLatest(IEnumerable<XElement> source, XmlConstants constant)
        {
            var result = (from investibleMeasure in source
                          let fromDate = investibleMeasure.Element(XmlConstants.EffvFromDt)
                          let toDate = investibleMeasure.Element(XmlConstants.EffvToDt)
                          let legacyType = investibleMeasure.Element(XmlConstants.LegacyType)
                          where !fromDate.IsNullOrEmpty() && !toDate.IsNullOrEmpty() 
                          orderby Convert.ToDateTime(fromDate.Value) descending
                          select investibleMeasure).FirstOrDefault();

            if (result != default(XElement))
                return result.Element(constant);
            return result;
        }

        public bool Initialise(XElement element, XmlConstants container, XmlConstants filter, string typeFilter)
        {
            AsOfDate = default(DateTime?);
            if (element.Descendants(XmlConstants.ParentMeasure).Any())
            {
                AsOfDate = (from investableMeasure in element.Descendants(XmlConstants.ParentMeasure)
                            let asOfDate = investableMeasure.Element(XmlConstants.EffvFromDt)
                            let measureType = investableMeasure.Element(XmlConstants.MeasureType)
                            where
                                !measureType.IsNullOrEmpty() && measureType.Value.Equals(typeFilter) &&
                                !asOfDate.IsNullOrEmpty()
                            let dateTime = Convert.ToDateTime(asOfDate.Value)
                            orderby dateTime descending
                            select dateTime
                           ).FirstOrDefault();
            }
            return base.Initialise(element, container, filter);
        }
       
    }
}
